import logging
import pandas as pd
import numpy as np
from typing import Dict, List, Any, Optional, Tuple
from datetime import datetime, timedelta
from collections import Counter

class TrendAnalyzer:
    """
    趋势分析器，负责分析AI资讯的热点趋势
    """
    
    def __init__(self, db_manager):
        """
        初始化趋势分析器
        
        Args:
            db_manager: 数据库管理器
        """
        self.logger = logging.getLogger("analyzer.trend")
        self.db_manager = db_manager
    
    def analyze_time_trend(self, days: int = 30, group_by: str = 'day', 
                          types: Optional[List[str]] = None) -> Dict[str, Any]:
        """
        分析时间趋势
        
        Args:
            days: 分析天数
            group_by: 分组方式 (day, week, month)
            types: 数据类型列表
            
        Returns:
            趋势分析结果
        """
        start_date = datetime.now() - timedelta(days=days)
        end_date = datetime.now()
        
        # 获取统计数据
        stats = self.db_manager.get_stats(start_date, end_date, group_by, types)
        
        # 转换为DataFrame便于分析
        rows = []
        for stat in stats:
            rows.append({
                'date': stat.get('date'),
                'type': stat.get('type'),
                'count': stat.get('count'),
                'categories': stat.get('category_stats', {})
            })
        
        if not rows:
            self.logger.warning("No data for trend analysis")
            return {
                'time_series': [],
                'category_trends': [],
                'period_comparison': {},
                'type_distribution': {}
            }
            
        df = pd.DataFrame(rows)
        
        # 1. 时间序列分析
        time_series = self._analyze_time_series(df)
        
        # 2. 类别趋势分析
        category_trends = self._analyze_category_trends(df)
        
        # 3. 环比/同比分析
        period_comparison = self._analyze_period_comparison(df, group_by)
        
        # 4. 类型分布分析
        type_distribution = self._analyze_type_distribution(df)
        
        return {
            'time_series': time_series,
            'category_trends': category_trends,
            'period_comparison': period_comparison,
            'type_distribution': type_distribution
        }
    
    def _analyze_time_series(self, df: pd.DataFrame) -> List[Dict[str, Any]]:
        """
        分析时间序列
        
        Args:
            df: 数据DataFrame
            
        Returns:
            时间序列分析结果
        """
        # 按日期和类型分组，计算每日数量
        if 'date' not in df.columns or df.empty:
            return []
            
        daily_counts = df.groupby(['date', 'type'])['count'].sum().reset_index()
        
        # 转换为时间序列结果
        result = []
        for date in sorted(daily_counts['date'].unique()):
            date_data = daily_counts[daily_counts['date'] == date]
            item = {'date': date}
            
            for _, row in date_data.iterrows():
                item[row['type']] = row['count']
                
            # 计算总数
            item['total'] = date_data['count'].sum()
            result.append(item)
            
        return result
    
    def _analyze_category_trends(self, df: pd.DataFrame) -> List[Dict[str, Any]]:
        """
        分析类别趋势
        
        Args:
            df: 数据DataFrame
            
        Returns:
            类别趋势分析结果
        """
        if 'categories' not in df.columns or df.empty:
            return []
            
        # 展平所有类别
        all_categories = {}
        for _, row in df.iterrows():
            date = row['date']
            categories = row['categories']
            
            for category, count in categories.items():
                if date not in all_categories:
                    all_categories[date] = {}
                    
                if category in all_categories[date]:
                    all_categories[date][category] += count
                else:
                    all_categories[date][category] = count
        
        # 找出最常见的10个类别
        category_counts = Counter()
        for date_cats in all_categories.values():
            for cat, count in date_cats.items():
                category_counts[cat] += count
                
        top_categories = [cat for cat, _ in category_counts.most_common(10)]
        
        # 构建每个类别的趋势数据
        result = []
        for category in top_categories:
            trend_data = {
                'category': category,
                'data': []
            }
            
            for date in sorted(all_categories.keys()):
                trend_data['data'].append({
                    'date': date,
                    'count': all_categories[date].get(category, 0)
                })
                
            result.append(trend_data)
            
        return result
    
    def _analyze_period_comparison(self, df: pd.DataFrame, group_by: str) -> Dict[str, Any]:
        """
        环比/同比分析
        
        Args:
            df: 数据DataFrame
            group_by: 分组方式
            
        Returns:
            环比/同比分析结果
        """
        if 'date' not in df.columns or df.empty:
            return {}
            
        # 确定时间间隔
        if group_by == 'day':
            current_period_days = 7
            prev_period_days = 7
            yoy_days = 365
        elif group_by == 'week':
            current_period_days = 28
            prev_period_days = 28
            yoy_days = 364
        elif group_by == 'month':
            current_period_days = 90
            prev_period_days = 90
            yoy_days = 365
        else:
            current_period_days = 30
            prev_period_days = 30
            yoy_days = 365
            
        # 转换日期格式
        df['date_obj'] = pd.to_datetime(df['date'], errors='coerce')
        
        if df['date_obj'].isna().all():
            # 日期格式无效
            return {}
            
        # 计算时间范围
        max_date = df['date_obj'].max()
        
        current_start = max_date - timedelta(days=current_period_days)
        prev_start = current_start - timedelta(days=prev_period_days)
        yoy_start = max_date - timedelta(days=yoy_days)
        
        # 环比分析（当前周期 vs 上一周期）
        current_period = df[(df['date_obj'] >= current_start) & (df['date_obj'] <= max_date)]
        prev_period = df[(df['date_obj'] >= prev_start) & (df['date_obj'] < current_start)]
        
        # 同比分析（当前周期 vs 去年同期）
        yoy_end = yoy_start + timedelta(days=current_period_days)
        yoy_period = df[(df['date_obj'] >= yoy_start) & (df['date_obj'] <= yoy_end)]
        
        # 计算总量
        current_total = current_period['count'].sum()
        prev_total = prev_period['count'].sum()
        yoy_total = yoy_period['count'].sum()
        
        # 计算环比和同比变化
        mom_change = 0
        if prev_total > 0:
            mom_change = (current_total - prev_total) / prev_total * 100
            
        yoy_change = 0
        if yoy_total > 0:
            yoy_change = (current_total - yoy_total) / yoy_total * 100
            
        # 类型分布变化
        type_changes = self._calculate_type_changes(current_period, prev_period)
        
        # 类别变化
        category_changes = self._calculate_category_changes(current_period, prev_period)
        
        return {
            'current_period': {
                'start': current_start.strftime('%Y-%m-%d'),
                'end': max_date.strftime('%Y-%m-%d'),
                'total': int(current_total)
            },
            'previous_period': {
                'start': prev_start.strftime('%Y-%m-%d'),
                'end': current_start.strftime('%Y-%m-%d'),
                'total': int(prev_total)
            },
            'yoy_period': {
                'start': yoy_start.strftime('%Y-%m-%d'),
                'end': yoy_end.strftime('%Y-%m-%d'),
                'total': int(yoy_total)
            },
            'mom_change': round(mom_change, 2),
            'yoy_change': round(yoy_change, 2),
            'type_changes': type_changes,
            'category_changes': category_changes
        }
    
    def _calculate_type_changes(self, current_df: pd.DataFrame, prev_df: pd.DataFrame) -> List[Dict[str, Any]]:
        """
        计算类型变化
        
        Args:
            current_df: 当前周期数据
            prev_df: 上一周期数据
            
        Returns:
            类型变化分析结果
        """
        if current_df.empty and prev_df.empty:
            return []
            
        # 当前周期类型分布
        current_types = current_df.groupby('type')['count'].sum().to_dict()
        
        # 上一周期类型分布
        prev_types = prev_df.groupby('type')['count'].sum().to_dict()
        
        # 计算变化
        changes = []
        all_types = set(list(current_types.keys()) + list(prev_types.keys()))
        
        for type_name in all_types:
            current_count = current_types.get(type_name, 0)
            prev_count = prev_types.get(type_name, 0)
            
            change_pct = 0
            if prev_count > 0:
                change_pct = (current_count - prev_count) / prev_count * 100
                
            changes.append({
                'type': type_name,
                'current_count': int(current_count),
                'previous_count': int(prev_count),
                'change_percentage': round(change_pct, 2)
            })
            
        # 按变化幅度排序
        changes.sort(key=lambda x: abs(x['change_percentage']), reverse=True)
        
        return changes
    
    def _calculate_category_changes(self, current_df: pd.DataFrame, prev_df: pd.DataFrame) -> List[Dict[str, Any]]:
        """
        计算类别变化
        
        Args:
            current_df: 当前周期数据
            prev_df: 上一周期数据
            
        Returns:
            类别变化分析结果
        """
        if 'categories' not in current_df.columns or (current_df.empty and prev_df.empty):
            return []
            
        # 当前周期类别统计
        current_categories = {}
        for _, row in current_df.iterrows():
            for category, count in row.get('categories', {}).items():
                if category in current_categories:
                    current_categories[category] += count
                else:
                    current_categories[category] = count
        
        # 上一周期类别统计
        prev_categories = {}
        for _, row in prev_df.iterrows():
            for category, count in row.get('categories', {}).items():
                if category in prev_categories:
                    prev_categories[category] += count
                else:
                    prev_categories[category] = count
        
        # 计算变化
        changes = []
        all_categories = set(list(current_categories.keys()) + list(prev_categories.keys()))
        
        for category in all_categories:
            current_count = current_categories.get(category, 0)
            prev_count = prev_categories.get(category, 0)
            
            change_pct = 0
            if prev_count > 0:
                change_pct = (current_count - prev_count) / prev_count * 100
                
            changes.append({
                'category': category,
                'current_count': int(current_count),
                'previous_count': int(prev_count),
                'change_percentage': round(change_pct, 2)
            })
            
        # 按变化幅度排序
        changes.sort(key=lambda x: abs(x['change_percentage']), reverse=True)
        
        # 仅返回前15个类别
        return changes[:15]
    
    def _analyze_type_distribution(self, df: pd.DataFrame) -> Dict[str, int]:
        """
        分析类型分布
        
        Args:
            df: 数据DataFrame
            
        Returns:
            类型分布结果
        """
        if 'type' not in df.columns or df.empty:
            return {}
            
        # 按类型分组，计算数量
        type_counts = df.groupby('type')['count'].sum()
        
        return type_counts.to_dict()
    
    def get_trending_topics(self, days: int = 7, limit: int = 10) -> List[Dict[str, Any]]:
        """
        获取热门话题
        
        Args:
            days: 天数
            limit: 返回数量
            
        Returns:
            热门话题列表
        """
        # 获取最近n天的数据
        start_date = datetime.now() - timedelta(days=days)
        
        # 查询条件
        query = {
            'created_at': {'$gte': start_date}
        }
        
        # 排序规则
        sort = [('popularity_score', -1), ('created_at', -1)]
        
        # 从数据库获取数据
        items = self.db_manager.get_items('news', query, sort, limit)
        
        # 统计热门话题
        topics = Counter()
        for item in items:
            for category in item.get('topic_categories', []):
                topics[category] += 1
                
        # 获取热门类别对应的最热门内容
        trending_topics = []
        for topic, count in topics.most_common(limit):
            query = {
                'created_at': {'$gte': start_date},
                'topic_categories': topic
            }
            topic_items = self.db_manager.get_items('news', query, [('popularity_score', -1)], 5)
            
            trending_topics.append({
                'topic': topic,
                'count': count,
                'top_items': topic_items
            })
            
        return trending_topics
    
    def get_popular_papers(self, days: int = 30, limit: int = 10) -> List[Dict[str, Any]]:
        """
        获取热门论文
        
        Args:
            days: 天数
            limit: 返回数量
            
        Returns:
            热门论文列表
        """
        # 获取最近n天的数据
        start_date = datetime.now() - timedelta(days=days)
        
        # 查询条件
        query = {
            'created_at': {'$gte': start_date},
            'type': 'paper'
        }
        
        # 排序规则：先按引用次数排序，再按时间排序
        sort = [('citation_count', -1), ('created_at', -1)]
        
        # 从数据库获取数据
        return self.db_manager.get_items('papers', query, sort, limit)
    
    def get_company_activity(self, days: int = 30) -> List[Dict[str, Any]]:
        """
        获取公司活动统计
        
        Args:
            days: 天数
            
        Returns:
            公司活动统计结果
        """
        # 获取最近n天的数据
        start_date = datetime.now() - timedelta(days=days)
        
        # 查询条件
        query = {
            'created_at': {'$gte': start_date},
            'type': 'company_news'
        }
        
        # 从数据库获取数据
        items = self.db_manager.get_items('news', query, limit=500)
        
        # 按公司分组
        company_stats = {}
        for item in items:
            company = item.get('company', 'Unknown')
            
            if company not in company_stats:
                company_stats[company] = {
                    'company': company,
                    'count': 0,
                    'items': [],
                    'latest_date': None
                }
                
            company_stats[company]['count'] += 1
            company_stats[company]['items'].append(item)
            
            # 记录最新日期
            item_date = item.get('published_date') or item.get('created_at')
            if isinstance(item_date, str):
                try:
                    item_date = datetime.fromisoformat(item_date.replace('Z', '+00:00'))
                except:
                    item_date = None
                    
            if item_date and (not company_stats[company]['latest_date'] or item_date > company_stats[company]['latest_date']):
                company_stats[company]['latest_date'] = item_date
        
        # 转换为列表并排序
        result = list(company_stats.values())
        result.sort(key=lambda x: x['count'], reverse=True)
        
        # 为每个公司保留最新的3条新闻
        for company_data in result:
            company_data['items'].sort(key=lambda x: x.get('published_date', ''), reverse=True)
            company_data['items'] = company_data['items'][:3]
            
            # 格式化日期
            if company_data['latest_date']:
                company_data['latest_date'] = company_data['latest_date'].isoformat()
                
        return result 